\subsubsection{GCC: x86-64}

\myindex{x86-64}
Попробуем GCC в 64-битном Linux:

\lstinputlisting[caption=GCC 4.4.6 x64,style=customasmx86]{patterns/01_helloworld/GCC_x64_RU.s}

В Linux, *BSD и \MacOSX для x86-64 также принят способ передачи аргументов функции через регистры \SysVABI.

6 первых аргументов передаются через регистры \RDI, \RSI, \RDX, \RCX, \Reg{8}, \Reg{9}, а остальные --- через стек.

Так что указатель на строку передается через \EDI (32-битную часть регистра).
Но почему не через 64-битную часть, \RDI?

Важно запомнить, что в 64-битном режиме все инструкции \MOV, записывающие что-либо в младшую 32-битную часть регистра, обнуляют старшие 32-бита (это можно найти в документации от Intel: \myref{x86_manuals}).
То есть, инструкция \INS{MOV EAX, 011223344h} корректно запишет это значение в \RAX, старшие биты сбросятся в ноль.

Если посмотреть в \IDA скомпилированный объектный файл (.o), увидим также опкоды всех инструкций
\footnote{Это нужно задать в \textbf{Options $\rightarrow$ Disassembly $\rightarrow$ Number of opcode bytes}}:

\lstinputlisting[caption=GCC 4.4.6 x64,style=customasmx86]{patterns/01_helloworld/GCC_x64.lst}

\label{hw_EDI_instead_of_RDI}
Как видно, инструкция, записывающая в \EDI по адресу \TT{0x4004D4}, занимает 5 байт.
Та же инструкция, записывающая 64-битное значение в \RDI, занимает 7 байт.
Возможно, GCC решил немного сэкономить.
К тому же, вероятно, он уверен, что сегмент данных, где хранится строка, никогда не будет расположен в адресах выше 4\gls{GiB}.

\label{SysVABI_input_EAX}
Здесь мы также видим обнуление регистра \EAX перед вызовом \printf.
Это делается потому что по упомянутому выше стандарту передачи аргументов в *NIX для x86-64 в \EAX передается количество задействованных векторных регистров.

